package com.ruoyi.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.util.StringUtil;
import com.ruoyi.api.entity.Message;
import com.ruoyi.api.service.VimGroupApiService;
import com.ruoyi.api.utils.SysGroup;
import com.ruoyi.api.utils.SysUtils;
import com.ruoyi.api.utils.Systrans;
import com.ruoyi.api.vo.*;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.UserInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.tio.StartTioRunner;
import com.ruoyi.vim.domain.ImGroup;
import com.ruoyi.vim.domain.ImGroupUser;
import com.ruoyi.vim.domain.TransImGroup;
import com.ruoyi.vim.domain.TransImGroupUser;
import com.ruoyi.vim.mapper.ImGroupMapper;
import com.ruoyi.vim.mapper.ImGroupUserMapper;
import com.ruoyi.vim.mapper.LocationMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.tio.core.Tio;
import org.tio.server.ServerTioConfig;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * vim 群操作类，如果需要对接其他的系统，重新下面的方法即可
 *
 * @author 乐天
 */
@Service
public class VimGroupApiServiceImpl implements VimGroupApiService {

    private static final String CACHE_KEY = "group";

    @Resource
    private ImGroupMapper imGroupMapper;

    @Resource
    private ImGroupUserMapper imGroupUserMapper;

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private LocationMapper locationMapper;

    @Resource
    private RedisCache redisCache;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 获取用户所在的群
     *
     * @param userId 用户id
     * @return List<Group>
     */
    @Override
    //@Cacheable(value = CACHE_KEY + ":list", key = "#userId")
    public List<Group> getGroups(String userId) {
        return imGroupMapper.getUserGroups(Long.valueOf(userId)).stream().map(this::transforms).collect(Collectors.toList());
    }

    /**
     * 获取群里所有的用户
     *
     * @param groupId 群id
     * @return List<User>
     */
    @Override
    public List<User> getUsers(String groupId) {
        return imGroupMapper.getGroupUsers(Long.valueOf(groupId)).stream().map(this::transform).collect(Collectors.toList());
    }

    /**
     * 获取群
     *
     * @param groupId 群id
     * @return Group
     */
    @Override
    public Group get(String groupId) {
        return transforms(imGroupMapper.selectByIds(Long.valueOf(groupId)));
    }

    /**
     * 给群新增用户
     *
     * @param groupId 群id
     * @param userIds 用户id，多个
     * @return 是否添加成功
     */
    @Override
    public boolean addUsers(String groupId, String[] userIds) {
        StartTioRunner startTioRunner = applicationContext.getBean(StartTioRunner.class);
        ServerTioConfig serverTioConfig = startTioRunner.getAppStarter().getWsServerStarter().getServerTioConfig();
        for (String userId : userIds) {
            List<String> list = imGroupUserMapper.selectByUserId(Long.valueOf(userId));
            for (String s : list) {
                if(s.equals(groupId)){
                    return false;
                }
            }
            ImGroupUser imGroupUser = new ImGroupUser();
            imGroupUser.setUserId(userId);
            imGroupUser.setGroupId(groupId);
            imGroupUser.setState("0");
            imGroupUser.setDelFlag("0");
            Systrans systrans = new Systrans();
            TransImGroupUser transImGroupUser = systrans.trans(imGroupUser);
            imGroupUserMapper.inserts(transImGroupUser);
            Tio.bindGroup(serverTioConfig, userId, groupId);
        }
        return true;
    }

    /**
     * 删除群用户
     *
     * @param groupId 群id
     * @param userIds 用户id，多个
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CACHE_KEY + ":user:list", key = "#groupId")
    public boolean delUsers(String groupId, String[] userIds) {
        StartTioRunner startTioRunner = applicationContext.getBean(StartTioRunner.class);
        ServerTioConfig serverTioConfig = startTioRunner.getAppStarter().getWsServerStarter().getServerTioConfig();
        for (String userId : userIds) {
//            QueryWrapper<TransImGroupUser> queryWrapper = new QueryWrapper<>();
//            queryWrapper.eq("user_id", Long.valueOf(userId));
//            queryWrapper.eq("group_id", Long.valueOf(groupId));
            imGroupUserMapper.deletes(Long.valueOf(userId),Long.valueOf(groupId));//有问题
            Tio.unbindGroup(serverTioConfig, userId, groupId);
        }
        return true;
    }

    /**
     * 删除一个群
     *
     * @param groupId 群Id
     * @return 删除数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {CACHE_KEY + ":user:list", CACHE_KEY + ":one"}, key = "#groupId")
    public int del(String groupId) {
        Long groupid = Long.valueOf(groupId);
        this.delUsers(groupId, getUsers(groupId).stream().map(User::getId).toArray(String[]::new));
        return imGroupMapper.deleteByIds(groupid);
    }

    /**
     * 群类型转换
     *
     * @param imGroup 群
     * @return Group
     */
    private Group transform(ImGroup imGroup) {
        return new Group(imGroup.getId(), imGroup.getName(), imGroup.getAvatar(), String.valueOf(imGroup.getMaster()), imGroup.getNeedCheck());
    }

    /**
     * 群类型转换
     *
     * @param transImGroup 群
     * @return Group
     */
    private Group transforms(TransImGroup transImGroup) {
        SysGroup sysGroup = new SysGroup();
        ImGroup imGroup = sysGroup.trans(transImGroup);
        return new Group(imGroup.getId(), imGroup.getName(), imGroup.getAvatar(), String.valueOf(imGroup.getMaster()), imGroup.getNeedCheck());
    }

    /**
     * 用户类型转换  long转string
     *
     * @param sysUser 用户
     * @return 群
     */
    private User transform(SysUser sysUser) {
        return new User(String.valueOf(sysUser.getUserId()), sysUser.getNickName(), sysUser.getAvatar(), sysUser.getMobile(), sysUser.getSex(), String.valueOf(sysUser.getDeptId()), sysUser.getEmail());
    }


    /**
     * 新建一个群
     *
     * @param group 群
     * @return Group
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    //@CacheEvict(value = CACHE_KEY + ":one", key = "#group.id")
    public Group save(Group group) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        ImGroup imGroup = new ImGroup();
        imGroup.setMaster(sysUser.getUserId());
        imGroup.setName(group.getName());
        imGroup.setAvatar(group.getAvatar());
        imGroup.setDelFlag(SysUtils.DEL_NO);
        imGroup.setNeedCheck(group.getNeedCheck());
//        imGroup.preInsert();
//        SysGroup sysGroup = new SysGroup();
//        TransImGroup transImGroup = sysGroup.tran(imGroup);
//        System.out.println(transImGroup);
        imGroupMapper.inserts(imGroup);
        String[] userIds = {String.valueOf(sysUser.getUserId())};
        Long a = imGroupMapper.selectByName(imGroup.getName(),imGroup.getMaster());
        this.addUsers(String.valueOf(a), userIds);
        imGroup.setId((a == null)? "null" : String.valueOf(a));
        return transform(imGroup);
    }

    /**
     * 更新一个群
     *
     * @param group 群
     * @return Group
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CACHE_KEY + ":one", key = "#group.id")
    public int update(Group group) {
        TransImGroup transImGroup = imGroupMapper.selectByIda(Long.valueOf(group.getId()));
        transImGroup.setName(group.getName());
        transImGroup.setAvatar(group.getAvatar());
        transImGroup.setNeedCheck(group.getNeedCheck());
        transImGroup.setDelFlag(SysUtils.DEL_NO);
        transImGroup.preUpdate();
        return imGroupMapper.updateByIds(transImGroup);
    }

    @Override
    public List<String> selectgroup(Long userId) {
        List<String> list = imGroupUserMapper.selectByUserId(userId);
        return list;
    }

    @Override
    public CurrentGroup selectUserLocation(String id) {
        CurrentGroup currentGroup = new CurrentGroup();
        Group group = get(id);
        currentGroup.setId(Long.valueOf(id));
        currentGroup.setAvater(group.getAvatar());
        currentGroup.setMaster(Long.valueOf(group.getMaster()));
        currentGroup.setName(group.getName());
        currentGroup.setNeedCheck(group.getNeedCheck());
        List<User> list = getUsers(id);
        List<String> stringList = new ArrayList<>();
        for (User user : list) {
            stringList.add(user.getName());
        }
        String a = StringUtils.join(stringList, ",");
        currentGroup.setMembar(a);
        List<UserListInfo> userListInfos = new ArrayList<>();
        List<String> locationList = new ArrayList<>();
        for (User user : list) {
            UserListInfo userListInfo = new UserListInfo();
            userListInfo.setId(Long.valueOf(user.getId()));
            userListInfo.setName(user.getName());
            String locatioin = locationMapper.selectUserLocation(user.getId());
            userListInfo.setPosition(locatioin);
            userListInfos.add(userListInfo);
            locationList.add(locatioin);
        }
        currentGroup.setUserListInfo(userListInfos);
        currentGroup.setCoor("211.11,12.11");
        currentGroup.setRadius("10");
        Date date = new Date();
        currentGroup.setTime(date);
        return currentGroup;
    }

    @Override
    public List<Long> getGroupsId(String userId) {
        List<Long> list = imGroupUserMapper.selectGroupId(Long.valueOf(userId));
        return list;
    }

    @Override
    public UnGroup selectunread(String userId, Long aLong) {
        UnGroup group = new UnGroup();
        String c = Long.toString(aLong);
        //获取上个查询时获取到的值
        Long a = redisCache.getCacheObject("count_group:" + userId + "_" + c);
        if(a == null) {
            a = 0L;
        }
        Long zSet = redisTemplate.opsForZSet().size("message-" + c);
        if(zSet != null){
            group.setUncount(Long.toString(zSet - a));
        }else {
            group.setUncount("0");
        }
        Set<ZSetOperations.TypedTuple<String>> set = redisTemplate.opsForZSet().reverseRangeWithScores("message-"  + aLong, 0, 0 );
            for (ZSetOperations.TypedTuple<String> stringTypedTuple : set) {
                String b = stringTypedTuple.getValue();
                Message message = JSON.parseObject(b,Message.class);
                group.setContent(message.getContent());
            }
        group.setGroupId(aLong);
        return group;
    }

    @Override
    public String selectById(Long aLong) {
        return imGroupMapper.selectByIdw(aLong);
    }
}
